#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <WiFiManager.h>
#include <WiFiUdp.h>
#include <NTPClient.h>

// NTP客户端配置
WiFiUDP ntpUDP;
NTPClient ntpClient(ntpUDP, "pool.ntp.org", 28800, 60000); // 东八区偏移量(28800秒)，每分钟同步一次

// 心知天气API配置
const char* weatherHost = "api.seniverse.com";
String reqUserKey = "SvBYLQk80Zh0w_Zya";  // 心知天气API密钥
String reqLocation = "Zhengzhou";           // 默认城市
String reqUnit = "c";                       // 温度单位

// 当前工作模式（0:自动模式，1:考勤签到，2：安全守护）
int currentMode = 0;

// Web服务器
ESP8266WebServer server(80);

// 天气数据结构（增加了城市和时区信息）
struct WeatherData {
  String city;            // 新增：城市名称
  String timezone;        // 新增：时区信息
  String date;
  String text_day;
  String code_day;
  String high;
  String low;
  String wind_dir;
  String wind_speed;
  String humidity;
  String last_update;
  bool isUpdated = false;
} weatherData;

// 天气更新参数
unsigned long lastWeatherUpdate = 0;
const unsigned long WEATHER_UPDATE_INTERVAL = 60000; // 60秒更新一次天气数据

// NTP更新参数
unsigned long lastNtpUpdate = 0;
const unsigned long NTP_UPDATE_INTERVAL = 60000; // 60秒更新一次NTP时间

// 串口时间发送参数
unsigned long lastSerialTimeSend = 0;
const unsigned long SERIAL_TIME_INTERVAL = 30000; // 30秒发送一次串口时间

// WiFiManager对象（关闭调试输出）
WiFiManager wifiManager;

// 调试开关
const bool DEBUG = false;

// 获取当前时间字符串（格式：YYMMDDHHMMSS，精确到秒）
String getFormattedTime() {
  time_t now = ntpClient.getEpochTime();
  struct tm *timeinfo;
  timeinfo = localtime(&now);
  
  // 格式：YYMMDDHHMMSS（12位）
  char buffer[13];
  sprintf(buffer, "%02d%02d%02d%02d%02d%02d", 
          timeinfo->tm_year % 100,    // 年后两位
          timeinfo->tm_mon + 1,       // 月
          timeinfo->tm_mday,          // 日
          timeinfo->tm_hour,          // 时
          timeinfo->tm_min,           // 分
          timeinfo->tm_sec            // 秒（新增）
         );
  return String(buffer);
}

// 获取当前时间字符串（用于Web显示：YYYY-MM-DD HH:MM:SS）
String getDisplayTime() {
  time_t now = ntpClient.getEpochTime();
  struct tm *timeinfo = localtime(&now);
  
  char buffer[20];
  sprintf(buffer, "%04d-%02d-%02d %02d:%02d:%02d",
          timeinfo->tm_year + 1900,
          timeinfo->tm_mon + 1,
          timeinfo->tm_mday,
          timeinfo->tm_hour,
          timeinfo->tm_min,
          timeinfo->tm_sec);
  return String(buffer);
}

// 生成HTML页面（修改工作模式）
String getHTML() {
  String html = "<!DOCTYPE html><html><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>动作控制器与天气显示</title><style>body{font-family:Arial;text-align:center;margin:20px;}h1{color:#444;}.button{background-color:#4CAF50;border:none;color:white;padding:15px 32px;text-align:center;text-decoration:none;display:inline-block;font-size:16px;margin:10px;cursor:pointer;border-radius:5px;box-shadow:0 4px 8px rgba(0,0,0,0.2);transition:all 0.3s;}.button:active{box-shadow:0 2px 4px rgba(0,0,0,0.4);transform:translateY(2px);}.button-mode-auto{background-color:#4CAF50;}.button-mode-attendance{background-color:#FF9800;}.button-mode-security{background-color:#f44336;}.info-box{background-color:#f0f0f0;padding:15px;margin:20px;border-radius:5px;}.weather-box{background-color:#e3f2fd;padding:15px;margin:20px;border-radius:5px;}.weather-code{color:#2196F3;font-weight:bold;}.city-selector{margin:15px;}.city-input{padding:10px;margin-right:5px;border:1px solid #ddd;border-radius:4px;}.city-button{padding:10px;background-color:#2196F3;color:white;border:none;border-radius:4px;cursor:pointer;}.phone-form{margin:20px;}.phone-input{padding:10px;margin:5px;border:1px solid #ddd;border-radius:4px;width:70%;}.phone-button{padding:10px;background-color:#FF9800;color:white;border:none;border-radius:4px;cursor:pointer;}.time-box{background-color:#fff3e0;padding:15px;margin:20px;border-radius:5px;border-left:4px solid #FF9800;}</style></head><body><h1>控制中心</h1>";
  
  // 1. 时间显示
  html += "<div class=\"time-box\" id=\"currentTime\"><h3>当前时间</h3><p>" + getDisplayTime() + "</p></div>";
  
  // 在</body>前添加自动刷新脚本
  html += "<script>"
          "function updateTime() {"
          "  fetch('/gettime').then(response => response.text()).then(data => {"
          "    document.getElementById('currentTime').querySelector('p').innerText = data;"
          "  });"
          "}"
          "setInterval(updateTime, 1000); // 每1秒刷新一次"
          "updateTime(); // 立即执行第一次更新"
          "</script>";  
  // 2. 网络状态
  html += "<div class=\"info-box\"><h3>网络状态</h3><p>当前连接: " + WiFi.SSID() + "</p><p>IP地址: " + WiFi.localIP().toString() + "</p></div>";
  
  // 3. 工作模式切换和人脸解析（替换原阈值设置部分）
  html += "<div class=\"info-box\"><h3>工作模式与功能</h3>"
          "<button class=\"button button-mode-auto\" onclick=\"setMode(0)\">自动模式</button>"
          "<button class=\"button button-mode-attendance\" onclick=\"setMode(1)\">考勤签到</button>"
          "<button class=\"button button-mode-security\" onclick=\"setMode(2)\">安全守护</button>"
          "<button class=\"button\" onclick=\"sendAction('faceres')\">解析人脸</button>"
          "</div>";
  
  // 4. 手机号输入（新增）
  html += "<div class=\"phone-form info-box\"><h3>手机号设置</h3>"
          "<input type=\"text\" class=\"phone-input\" id=\"phoneNumber\" placeholder=\"输入11位手机号\" maxlength=\"11\">"
          "<button onclick=\"sendPhoneNumber()\" class=\"phone-button\">确认</button>"
          "</div>";
  
  // 5. 城市选择
  html += "<div class=\"city-selector\">"
          "<form action=\"/setcity\" method=\"get\">"
          "<input type=\"text\" class=\"city-input\" name=\"city\" placeholder=\"输入城市名称\" value=\"" + reqLocation + "\">"
          "<button type=\"submit\" class=\"city-button\">更改城市</button>"
          "</form>"
          "</div>";
  
  // 6. 天气信息
  html += "<div class=\"weather-box\"><h3>天气信息</h3>";
  if (weatherData.isUpdated) {
    html += "<p>城市: " + weatherData.city + "</p>"
            "<p>时区: " + weatherData.timezone + "</p>"
            "<p>日期: " + weatherData.date + "</p>"
            "<p>白天天气: " + weatherData.text_day + " <span class=\"weather-code\">" + weatherData.code_day + "</span></p>"
            "<p>温度: " + weatherData.low + "°C ~ " + weatherData.high + "°C</p>"
            "<p>风向: " + weatherData.wind_dir + ", 风速: " + weatherData.wind_speed + " m/s</p>"
            "<p>湿度: " + weatherData.humidity + "%</p>"
            "<p style=\"font-size:12px;color:#666;\">更新时间: " + weatherData.last_update + "</p>";
  } else {
    html += "<p>加载天气信息中...</p>";
  }
  html += "</div>"
          "<script>function sendAction(action){fetch('/' + action).then(r=>r.text()).then(d=>console.log(d));}"
          "function setMode(mode){fetch('/setmode?mode=' + mode).then(r=>r.text()).then(d=>{"
          "  document.querySelectorAll('.button-mode-auto, .button-mode-attendance, .button-mode-security').forEach(btn=>btn.className='button');"
          "  if(mode === 0) document.querySelector('.button-mode-auto').className='button button-mode-auto';"
          "  else if(mode === 1) document.querySelector('.button-mode-attendance').className='button button-mode-attendance';"
          "  else if(mode === 2) document.querySelector('.button-mode-security').className='button button-mode-security';"
          "  console.log(d);"
          "});}"
          "function sendPhoneNumber(){"
          "  let phone = document.getElementById('phoneNumber').value;"
          "  if(phone.length === 11 && /^1[3-9]\\d{9}$/.test(phone)){"
          "    fetch('/setphone?phone=' + phone).then(r=>r.text()).then(d=>{"
          "      alert(d);"
          "      document.getElementById('phoneNumber').value = '';"
          "    });"
          "  } else {"
          "    alert('请输入有效的11位手机号');"
          "  }"
          "}</script>"
          "</body></html>";
  
  return html;
}

// 获取天气数据的HTML片段（更新显示内容）
String getWeatherHTML() {
  if (weatherData.isUpdated) {
    return "<p>城市: " + weatherData.city + " (" + weatherData.timezone + ")</p>" +
           "<p>日期: " + weatherData.date + "</p>" +
           "<p>白天天气: " + weatherData.text_day + " <span class=\"weather-code\">" + weatherData.code_day + "</span></p>" +
           "<p>温度: " + weatherData.low + "°C ~ " + weatherData.high + "°C</p>" +
           "<p>风向: " + weatherData.wind_dir + ", 风速: " + weatherData.wind_speed + " m/s</p>" +
           "<p>湿度: " + weatherData.humidity + "%</p>" +
           "<p style=\"font-size:12px;color:#666;\">更新时间: " + weatherData.last_update + "</p>";
  } else {
    return "<p>加载天气信息中...</p>";
  }
}

// 从心知天气API获取天气数据（更新JSON解析逻辑）
bool fetchWeatherData() {
  WiFiClient client;
  if (!client.connect(weatherHost, 80)) {
    if (DEBUG) Serial.println("无法连接天气服务器");
    return false;
  }

  String reqRes = "/v3/weather/daily.json?key=" + reqUserKey +
                  "&location=" + reqLocation + "&language=en&unit=" + reqUnit + "&start=0&days=1";
  String httpRequest = "GET " + reqRes + " HTTP/1.1\r\n" +
                       "Host: " + weatherHost + "\r\n" +
                       "Connection: close\r\n\r\n";
  client.print(httpRequest);

  // 跳过响应头
  if (!client.find("\r\n\r\n")) {
    if (DEBUG) Serial.println("响应头解析失败");
    client.stop();
    return false;
  }

  // JSON解析（更新解析逻辑，增加城市和时区信息）
  const size_t capacity = JSON_OBJECT_SIZE(1) + JSON_ARRAY_SIZE(1) + 
                          JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(6) + 
                          JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(14) + 
                          JSON_OBJECT_SIZE(7) + 500; // 增加容量
  DynamicJsonDocument doc(capacity);
  DeserializationError error = deserializeJson(doc, client);
  client.stop();

  if (error) {
    if (DEBUG) Serial.print("天气解析错误: ");
    if (DEBUG) Serial.println(error.c_str());
    return false;
  }

  if (!doc["results"].size()) {
    if (DEBUG) Serial.println("无天气数据");
    return false;
  }

  // 解析位置信息（新增）
  JsonObject location = doc["results"][0]["location"];
  weatherData.city = location["name"].as<const char*>();
  weatherData.timezone = location["timezone"].as<const char*>();
  
  // 解析天气数据
  JsonObject today = doc["results"][0]["daily"][0];
  weatherData.date = today["date"].as<const char*>();
  weatherData.text_day = today["text_day"].as<const char*>();
  weatherData.code_day = today["code_day"].as<const char*>();
  weatherData.low = today["low"].as<const char*>();
  weatherData.high = today["high"].as<const char*>();
  weatherData.wind_dir = today["wind_direction"].as<const char*>();
  weatherData.wind_speed = today["wind_speed"].as<const char*>();
  weatherData.humidity = today["humidity"].as<const char*>();
  weatherData.last_update = doc["results"][0]["last_update"].as<const char*>();
  weatherData.isUpdated = true;

  if (DEBUG) {
    Serial.println("天气数据更新成功");
    Serial.println("城市: " + weatherData.city);
    Serial.println("时区: " + weatherData.timezone);
  }

  return true;
}

// 处理根路径请求（修复乱码）
void handleRoot() {
  server.send(200, "text/html; charset=UTF-8", getHTML());
}

// 处理人脸解析请求
void handleFaceRes() {
  Serial.println("faceres"); // 发送人脸解析命令
  server.send(200, "text/plain; charset=UTF-8", "人脸解析命令已发送");
}

// 处理天气数据请求（修复乱码）
void handleWeather() {
  server.send(200, "text/html; charset=UTF-8", getWeatherHTML());
}

// 处理设置城市请求（修复乱码）
void handleSetCity() {
  if (server.hasArg("city")) {
    reqLocation = server.arg("city");
    if (fetchWeatherData()) {
      server.send(200, "text/html; charset=UTF-8", "<script>alert('城市已更改为: " + reqLocation + "');window.location.href='/';</script>");
    } else {
      server.send(200, "text/html; charset=UTF-8", "<script>alert('城市更新失败，请检查城市名称');window.location.href='/';</script>");
    }
  } else {
    server.send(400, "text/plain; charset=UTF-8", "错误: 未提供城市名称");
  }
}

// 处理设置工作模式请求（新增）
void handleSetMode() {
  if (server.hasArg("mode")) {
    String modeArg = server.arg("mode");
    int newMode = modeArg.toInt();
    
    if (newMode >= 0 && newMode <= 2) { // 支持0-2三种模式
      currentMode = newMode;
      String modeStr = "";
      String modeName = "";
      
      // 根据模式生成发送的命令和显示名称
      switch(newMode) {
        case 0:
          modeStr = "conmod0";
          modeName = "自动模式";
          break;
        case 1:
          modeStr = "conmod1";
          modeName = "考勤签到";
          break;
        case 2:
          modeStr = "conmod2"; // 新增模式2的命令
          modeName = "安全守护";
          break;
      }
      
      Serial.println(modeStr); // 发送模式命令
      
      // 构建响应消息
      String response = "工作模式已设置为: " + modeName;
      server.send(200, "text/plain; charset=UTF-8", response);
    } else {
      server.send(400, "text/plain; charset=UTF-8", "错误: 无效的模式值 (支持0-2)");
    }
  } else {
    server.send(400, "text/plain; charset=UTF-8", "错误: 缺少模式参数");
  }
}

// 处理设置手机号请求（新增）
void handleSetPhone() {
  if (server.hasArg("phone")) {
    String phone = server.arg("phone");
    
    // 简单验证手机号格式
    if (phone.length() == 11 && phone.startsWith("1") && phone.substring(1).toInt() > 0) {
      String phoneData = "ph:" + phone;
      Serial.println(phoneData); // 发送手机号命令
      
      // 修复字符串连接问题
      String response = "手机号已设置: " + phone;
      server.send(200, "text/plain; charset=UTF-8", response);
    } else {
      server.send(200, "text/plain; charset=UTF-8", "错误: 请输入有效的11位手机号");
    }
  } else {
    server.send(400, "text/plain; charset=UTF-8", "错误: 缺少手机号参数");
  }
}

// 配置WiFi连接（关闭WiFiManager调试输出）
void configureWiFi() {
  wifiManager.setDebugOutput(false); // 关键修改：关闭*WM调试信息
  // 设置AP模式热点名称和密码
  wifiManager.setAPStaticIPConfig(IPAddress(192, 168, 4, 1), IPAddress(192, 168, 4, 1), IPAddress(255, 255, 255, 0));
  wifiManager.autoConnect("ESP8266-Config", "12345678"); // AP热点名称和密码
  
  // 仅输出IP地址
  Serial.print("IP:");
  Serial.println(WiFi.localIP());
}

void setup() {
  Serial.begin(9600);
  
  // 配置WiFi
  configureWiFi();
  
  // 初始化NTP客户端
  ntpClient.begin();
  ntpClient.update(); // 首次获取时间
  
  // 首次获取天气数据
  fetchWeatherData();
  
  // 设置服务器路由（移除手动告警路由）
  server.on("/", handleRoot);
  server.on("/faceres", handleFaceRes); // 人脸解析路由
  server.on("/weather", handleWeather);
  server.on("/setcity", handleSetCity);
  server.on("/setmode", handleSetMode); // 模式设置路由
  server.on("/setphone", handleSetPhone); // 手机号设置路由
  server.on("/gettime", [](){
    server.send(200, "text/plain; charset=UTF-8", getDisplayTime());
  });
  
  // 启动服务器
  server.begin();
}

void loop() {
  // 处理客户端请求
  server.handleClient();
  
  // 定期更新NTP时间
  if (millis() - lastNtpUpdate >= NTP_UPDATE_INTERVAL) {
    lastNtpUpdate = millis();
    ntpClient.update();
  }
  
  // 定期更新天气数据（每20秒）
  if (millis() - lastWeatherUpdate >= WEATHER_UPDATE_INTERVAL) {
    lastWeatherUpdate = millis();
    fetchWeatherData();
  }
  
  // 定期通过串口发送时间（每10秒）
  if (millis() - lastSerialTimeSend >= SERIAL_TIME_INTERVAL) {
    lastSerialTimeSend = millis();
    String timeStr = getFormattedTime();
    Serial.println(timeStr); // 格式：YYMMDDHHMMSS（精确到秒）
  }
}